#!/usr/bin/env python3

# Copyright (c) 2020-2021 Fpemud <fpemud@sina.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.


import os
import enum
import shutil
from ..._util import Util, WinRegistry
from ..._prototype import CustomAction
from ..._vm import Vm


class SetResolution(CustomAction):

    def __init__(self, width, height):
        assert 0 < width <= 0xFFFF and 0 < height <= 0xFFFF
        self._width = width
        self._height = height

    def run(self, action_name, s, ts, work_dir):
        selfDir = os.path.dirname(os.path.realpath(__file__))

        with work_dir.mount_image_file() as mp:
            # put needed files into virtual machine disk
            shutil.copy(os.path.join(selfDir, "..", "tool-qres.exe"), mp.drive_c_dir)
            # add runonce registry entry
            reg = WinRegistry(mp.drive_c_dir)
            self.add_runonce_command(reg, 'C:\\tool-qres.exe /X %d /Y %d' % (self._width, self._height))
            self.add_runonce_command(reg, 'del C:\\tool-qres.exe')

        # run vm
        vm = Vm(work_dir)
        vm.start(show=(s.verbose_level > 0))
        try:
            vm.wait_until_stable()
            vm.shutdown()
            vm.wait_until_stop()
        except BaseException:
            vm.stop()
            raise

    def get_after(self):
        return []

    def get_before(self):
        return []


class SetBackground(CustomAction):

    class BackgroundType(enum.Enum):
        SOLID_COLOR = enum.auto()
        STOCK_WALLPAPER = enum.auto()
        CUSTOM_WALLPAPER = enum.auto()

    def __init__(self, background_type, *kargs, for_user=None):
        self._bgType = background_type
        if self._bgType == self.BackgroundType.SOLID_COLOR:
            self._color = kargs[0]
        elif self._bgType == self.BackgroundType.STOCK_WALLPAPER:
            self._path = kargs[0]
            self._position = kargs[1]
        elif self._bgType == self.BackgroundType.CUSTOM_WALLPAPER:
            self._path = kargs[0]
            self._position = kargs[1]
        else:
            assert False

        self._user = for_user

    def run(self, action_name, s, ts, work_dir):
        with work_dir.mount_image_file() as mp:
            reg = WinRegistry(mp.drive_c_dir)
            if self._bgType == self.BackgroundType.SOLID_COLOR:
                for u in Util.getListByItem(reg.get_users(), self._user):
                    reg.modify("HKU\\%s\\Control Panel\\Colors" % (u), "Background", "REG_SZ", self._convertColorNumber(self._color))
                    reg.delete("HKU\\%s\\Control Panel\\Desktop" % (u), "Wallpaper")
            elif self._bgType == self.BackgroundType.STOCK_WALLPAPER:
                # FIXME
                assert False
            elif self._bgType == self.BackgroundType.CUSTOM_WALLPAPER:
                # FIXME
                assert False
            else:
                assert False

    def get_after(self):
        return []

    def get_before(self):
        return []

    @staticmethod
    def _convertColorNumber(color_hex):
        assert 0x000000 <= color_hex <= 0xFFFFFF
        r = (color_hex >> 16) & 0xFF
        g = (color_hex >> 8) & 0xFF
        b = color_hex & 0xFF
        return f"{r} {g} {b}"


class DisableAutoRun(CustomAction):

    def run(self, action_name, s, ts, work_dir):
        with work_dir.mount_image_file() as mp:
            reg = WinRegistry(mp.drive_c_dir)
            reg.modify("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", "NoDriveTypeAutoRun", "REG_DWORD", 255)

    def get_after(self):
        return []

    def get_before(self):
        return []


class DisableNetworkLocationWizard(CustomAction):

    def __init__(self, for_user=None):
        self._user = for_user

    def run(self, action_name, s, ts, work_dir):
        with work_dir.mount_image_file() as mp:
            reg = WinRegistry(mp.drive_c_dir)
            for u in Util.getListByItem(reg.get_users(), self._user):
                reg.add_or_modify("HKU\\%s\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Network\\NwCategoryWizard" % (u), "Show", "REG_DWORD", 0)

        # There's another solution
        #    Name: HideWizard (DWORD)
        #    Value: 1
        # There's another solution
        #    reg.add("HKLM\\SYSTEM\\CurrentControlSet\\Control\\Network\\NewNetworkWindowOff" % (u), "dummy", "REG_DWORD", 0)
        #    but add key NewNetworkWindowOff is enough, but WinRegistry has only add-value interface

    def get_after(self):
        return []

    def get_before(self):
        return []


class DisablePublisherVerification(CustomAction):

    def __init__(self, for_user=None):
        self._user = for_user

    def run(self, action_name, s, ts, work_dir):
        with work_dir.mount_image_file() as mp:
            reg = WinRegistry(mp.drive_c_dir)
            for u in Util.getListByItem(reg.get_users(), self._user):
                # here "*.*" has no effect
                reg.add_or_modify("HKU\\%s\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Associations" % (u), "LowRiskFileTypes", "REG_SZ", "*.bat;*.exe;*.com")

    def get_after(self):
        return []

    def get_before(self):
        return []


class DisableAutoRestartAfterWindowsUpdate(CustomAction):

    def run(self, action_name, s, ts, work_dir):
        with work_dir.mount_image_file() as mp:
            reg = WinRegistry(mp.drive_c_dir)
            reg.add_or_modify("HKLM\\SOFTWARE\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU", "NoAutoRebootWithLoggedOnUsers", "REG_DWORD", 1)
        # This prevents automatic restart but doesn't stop the nagging notification that takes you out of games and full screen video every 4 hours.
        # Is it true?
        #
        # Note that there are other keys, such as AlwaysAutoRebootAtScheduledTime and AlwaysAutoRebootAtScheduledTimeMinutes, that can also influence automatic rebooting.
        # Is it true?
        #
        # https://learn.microsoft.com/en-us/windows/deployment/update/waas-restart
        #

    def get_after(self):
        return []

    def get_before(self):
        return []
